package org.lilred.nzbberry.controllers;

import java.util.Timer;
import java.util.TimerTask;

import org.lilred.nzbberry.models.ConfigModel;
import org.lilred.nzbberry.models.QueueModel;
import org.lilred.nzbberry.observer.Observer;
import org.lilred.nzbberry.views.AppView;
import org.lilred.nzbberry.webservice.SabnzbdActionClient;

import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.FieldChangeListener;
import net.rim.device.api.ui.MenuItem;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.Menu;

public class AppController implements Observer, FieldChangeListener {
	//Singleton
	private static final AppController INSTANCE = new AppController();
	public static AppController getInstance() {
		return INSTANCE;
	}

	public static final int STARTED = 0;
	public static final int COMPLETED = 1;
	public static final int ERROR = 2;
	public static final int EMPTY = 3;

	//Declare models
	QueueModel queueModel;

	//Declare controllers
	PageController pageController; //A reference to the currently active page controller
	PageController lastPageController;
	QueueController queueController;
	PluginController pluginController;
	ConfigController configController;
	HistoryController historyController;
	SearchController searchController;

	//Declare views
	AppView view;
	//QueueView queueView;
	//PluginView pluginView;

	Timer queueIndicatorTimer;

	private AppController() {
		//Initialize all the models, views, and controllers
		queueModel = new QueueModel();
		queueController = new QueueController(queueModel);
		queueController.registerObserver(this);
		setPageController(queueController);
		configController = new ConfigController();
		configController.registerObserver(this);
		historyController = new HistoryController();
		historyController.registerObserver(this);
		searchController = new SearchController();

		view = new AppView() {
			protected void makeMenu(Menu menu, int instance) {
				pageController.makeMenu(menu);
				menu.addSeparator();
				menu.add(refreshAllMenuItem);
				if (queueModel.paused) menu.add(globalUnpauseMenuItem);
				else menu.add(globalPauseMenuItem);
				super.makeMenu(menu, instance);
			}
		};
		view.appManager.queueButton.setChangeListener(this);
		view.appManager.historyButton.setChangeListener(this);
		view.appManager.searchButton.setChangeListener(this);
		view.appManager.configButton.setChangeListener(this);
		UiApplication.getUiApplication().invokeLater(new Runnable() {
			public void run() {
				UiApplication.getUiApplication().pushScreen(view);
			}
		});
		
		long refreshCurrentInterval = ConfigModel.getConfig().getRefreshCurrentInterval();
		long refreshAllInterval = ConfigModel.getConfig().getRefreshAllInterval();
		scheduledUpdateTimer.schedule(scheduledUpdateTask, refreshCurrentInterval, refreshCurrentInterval);
		scheduledUpdateAllTimer.schedule(scheduledUpdateAllTask, refreshCurrentInterval, refreshAllInterval);
	}

	public void setPageController(PageController c) {
		if (c == searchController) { 
			UiApplication.getUiApplication().pushScreen(searchController.searchView); 
			return;
		}
		//remove existing menu items
		lastPageController = pageController;
		UiApplication.getUiApplication().invokeLater(new Runnable() {
			public void run() {
				if (lastPageController != null) {
					for (int i = 0; i < lastPageController.menuItems.size(); i++) {
						view.removeMenuItem((MenuItem) lastPageController.menuItems.elementAt(i));
					}
				}
			}
		});
		pageController = c;
		//add new menu items
		UiApplication.getUiApplication().invokeLater(new Runnable() {
			public void run() {
				for (int i = 0; i < pageController.menuItems.size(); i++) {
					view.addMenuItem((MenuItem) pageController.menuItems.elementAt(i));
				}
				view.appManager.setPageView(pageController.view);
			}
		});
	}

	Timer scheduledUpdateTimer = new Timer();
	TimerTask scheduledUpdateTask = new TimerTask() {
		public void run() {
			if (view.isVisible()) {
				if (pageController == queueController) {
					queueController.refresh();
				} else if (pageController == configController) {
					configController.refresh();
				} else if (pageController == historyController) {
					historyController.refresh();
				}
			}
		}
	};

	Timer scheduledUpdateAllTimer = new Timer();
	TimerTask scheduledUpdateAllTask = new TimerTask() {
		public void run() {
			if (UiApplication.getUiApplication().isForeground()) {
				refreshAll();
			}
		}
	};

	public void refreshAll() {
		queueController.refresh();
		configController.refresh();
		historyController.refresh();
	}

	public void globalPause() {
		AppView.getInstance().appManager.updateBanner("Paused", "Uptime: " + queueModel.uptime);
		SabnzbdActionClient pauseClient = new SabnzbdActionClient();
		queueModel.paused = true;
		pauseClient.pause();
		queueController.refresh();
	}

	public void globalUnpause() {
		AppView.getInstance().appManager.updateBanner(queueModel.kbps, queueModel.timeleft);
		SabnzbdActionClient unpauseClient = new SabnzbdActionClient();
		queueModel.paused = false;
		unpauseClient.Unpause();
		queueController.refresh();
	}
	
	public void updateObserver(Object o, int context) {
		switch (context) {
		case STARTED:
			view.appManager.queueIndicatorField.setColor(0xFFFF00);
			break;
		case COMPLETED:
			view.appManager.queueIndicatorField.setColor(0x00FF00);
			if (o == queueController) {
				if (queueModel.size() == 0) view.appManager.updateBanner("Queue Empty", "Uptime: " + queueModel.uptime);
				else if (queueModel.paused) view.appManager.updateBanner("Paused", "Uptime: " + queueModel.uptime); 
				else {
					view.appManager.updateBanner(queueController.getKbps(), queueController.getTimeLeft());
				}
			}
			break;
		case ERROR:
			view.appManager.queueIndicatorField.setColor(0xFF0000);
			break;
		}
	}

	public void fieldChanged(Field field, int context) {
		if (field == view.appManager.queueButton) setPageController(queueController);
		if (field == view.appManager.configButton) setPageController(configController);
		if (field == view.appManager.historyButton) setPageController(historyController);
		if (field == view.appManager.searchButton) setPageController(searchController); 
	}

	public MenuItem refreshAllMenuItem = new MenuItem("Refresh All", 100, 100) {
		public void run() { refreshAll(); }
	};

	public MenuItem globalPauseMenuItem = new MenuItem("Global Pause", 110, 110) {
		public void run() { globalPause(); }
	};

	public MenuItem globalUnpauseMenuItem = new MenuItem("Global Unpause", 110, 110) {
		public void run() { globalUnpause(); }
	};	
}
